﻿using System;
using System.Text;

using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace Common
{
    public static class Serializer
    {
        public static byte[] Serialize(this object obj)
        {
            return Serializer.SerializeObject(obj);
        }

        public static bool Serialize(this object obj, Stream stream)
        {
            byte[] data = Serializer.SerializeObject(obj);
            stream.Write(data, 0, data.Length);

            return true;
        }

        public static bool Serialize(this object obj, String file_path)
        {
            if (obj is ISecureSerializable)
            {
                ISecureSerializable ss = obj as ISecureSerializable;

                using (SoftwareLock sl = new SoftwareLock(file_path))
                {
                    if ((Serializer.DeserializeObject(file_path, obj.GetType()) as ISecureSerializable).TimeStamp != ss.TimeStamp)
                        return false;

                    ss.TimeStamp = DateTime.UtcNow;
                    Serializer.SerializeObject(obj, file_path);
                }
            }
            else
            {
                Serializer.SerializeObject(obj, file_path);
            }

            return true;
        }

        public static void SerializeObject(Object my_object, String file_path)
        {
            FileHelper.WriteAllByte(file_path, SerializeObject(my_object));
        }

        public static byte[] SerializeObject(Object my_object)
        {
            try
            {
                MemoryStream memoryStream = new MemoryStream();
                XmlSerializer xs = new XmlSerializer(my_object.GetType());
                XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);

#               if DEBUG
                xmlTextWriter.Formatting = Formatting.Indented;
#               endif

                xs.Serialize(xmlTextWriter, my_object);
                memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
                return memoryStream.ToArray();
            }
            catch (Exception e)
            {
                System.Console.WriteLine(e);
                return null;
            }
        }

        public static T Deserialize<T>(this T obj, byte[] data, ref T value)
        {
            return value = (T)(Serializer.DeserializeObject(data, typeof(T)));
        }

        public static T Deserialize<T>(this T obj, Stream stream, ref T value)
        {
            byte[] data = new byte[stream.Length];
            stream.Read(data, 0, (int)stream.Length);

            return obj.Deserialize(data, ref value);
        }

        public static T Deserialize<T>(this T obj, String file_path)
        {
            return (T)(Serializer.DeserializeObject(file_path, typeof(T)));
        }

        public static T Deserialize<T>(this T obj, String file_path, ref T value)
        {
            return value = obj.Deserialize(file_path);
        }

        public static Object DeserializeObject(String file_path, Type type)
        {
            return DeserializeObject(FileHelper.ReadAllByte(file_path), type);
        }

        public static Object DeserializeObject(byte[] xml_content, Type type)
        {
            XmlSerializer xs = new XmlSerializer(type);
            MemoryStream memoryStream = new MemoryStream(xml_content);
            XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);

            return xs.Deserialize(memoryStream);
        }
    }
}
